home *** CD-ROM | disk | FTP | other *** search
/ Cre@te Online 2000 December / Cre@teOnline CD05.iso / MacSoft / XML Instance.sea / XML Instance / Required / plugins / HTMLWindow.jar / horst / parser / HTMLParser.class (.txt) < prev    next >
Encoding:
Java Class File  |  2000-03-18  |  13.6 KB  |  1,003 lines

  1. package horst.parser;
  2.  
  3. import java.io.BufferedOutputStream;
  4. import java.io.BufferedReader;
  5. import java.io.File;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8. import java.io.InputStream;
  9. import java.io.InputStreamReader;
  10. import java.io.Reader;
  11. import java.net.URL;
  12. import java.net.URLConnection;
  13.  
  14. public class HTMLParser implements ParserCallback {
  15.    private static final int TEXT_STATE = 1;
  16.    private static final int TAG_STATE = 2;
  17.    private static final int COMMENT_STATE = 3;
  18.    private static final int TAGQUOTE_STATE = 5;
  19.    private static final int ENTITYREF_STATE = 6;
  20.    private static final int SCRIPT_TAG_STATE = 7;
  21.    private static final int CARRIAGE_RETURN = 13;
  22.    private static final int NEWLINE = 10;
  23.    private static final int TAB = 9;
  24.    private static final char SINGLEQUOTE = '\'';
  25.    private static final char DOUBLEQUOTE = '"';
  26.    private static final int TYPE_LEN = 256;
  27.    private static final byte T_WHITESPACE = 1;
  28.    private static char[] m_scriptTag = new char[9];
  29.    private static byte[] m_ctype = new byte[256];
  30.    private static Escapes m_escapes = new Escapes();
  31.    ParserCallback m_callback = this;
  32.    Reader m_in;
  33.    int m_lineNum = 0;
  34.    int m_tagquote;
  35.    int m_comment;
  36.    int m_script;
  37.    StringBuffer m_buf = new StringBuffer();
  38.    StringBuffer m_entityBuffer = new StringBuffer();
  39.    StringBuffer m_scriptBuffer = new StringBuffer();
  40.    int m_parserState = 1;
  41.    int m_ch;
  42.    boolean m_bSpace;
  43.    boolean m_bPreformat;
  44.    boolean m_bNoBreakSpace;
  45.    BufferedOutputStream m_out;
  46.    TagGenerator m_generator = new HTMLTags();
  47.    boolean m_bPlainText;
  48.    Tag m_lastTag;
  49.  
  50.    static {
  51.       m_scriptTag[0] = '<';
  52.       m_scriptTag[1] = '/';
  53.       m_scriptTag[2] = 's';
  54.       m_scriptTag[3] = 'c';
  55.       m_scriptTag[4] = 'r';
  56.       m_scriptTag[5] = 'i';
  57.       m_scriptTag[6] = 'p';
  58.       m_scriptTag[7] = 't';
  59.       m_scriptTag[8] = '>';
  60.       int len = m_ctype.length;
  61.  
  62.       for(int i = 0; i < len; ++i) {
  63.          m_ctype[i] = 0;
  64.       }
  65.  
  66.       m_ctype[32] = 1;
  67.       m_ctype[13] = 1;
  68.       m_ctype[10] = 1;
  69.       m_ctype[9] = 1;
  70.  
  71.       for(int i = 14; i <= 31; ++i) {
  72.          m_ctype[i] = 1;
  73.       }
  74.  
  75.    }
  76.  
  77.    private void beginParsing(URLConnection con) throws IOException {
  78.       String contentType = con.getContentType();
  79.       if (contentType != null) {
  80.          this.m_bPlainText = contentType.equals("text/plain");
  81.       }
  82.  
  83.       InputStream istream = con.getInputStream();
  84.       this.m_in = new BufferedReader(new InputStreamReader(istream), 16384);
  85.       this.m_buf = new StringBuffer();
  86.       this.m_entityBuffer = new StringBuffer();
  87.       this.m_scriptBuffer = new StringBuffer();
  88.       System.gc();
  89.       this.m_callback.startingParsing(con.getURL());
  90.       if (this.m_bPlainText) {
  91.          this.m_callback.handleTag(this.m_generator.getTag("html"), true);
  92.          this.m_callback.handleTag(this.m_generator.getTag("pre"), true);
  93.       }
  94.  
  95.       this.parseContent();
  96.       if (this.m_bPlainText) {
  97.          this.m_callback.handleTag(this.m_generator.getTag("html"), false);
  98.          this.m_callback.handleTag(this.m_generator.getTag("pre"), false);
  99.       }
  100.  
  101.       this.m_callback.finishedParsing();
  102.       this.m_callback = null;
  103.    }
  104.  
  105.    private final void callbackContent() {
  106.       this.m_lastTag = null;
  107.       if (this.m_bNoBreakSpace) {
  108.          this.m_bNoBreakSpace = false;
  109.          int i = 0;
  110.          int buflen = this.m_buf.length();
  111.  
  112.          int buflen_minus1;
  113.          for(buflen_minus1 = buflen - 1; i < buflen && !Character.isWhitespace(this.m_buf.charAt(i)); ++i) {
  114.          }
  115.  
  116.          if (i == buflen_minus1 && buflen > 1) {
  117.             StringBuffer temp = new StringBuffer();
  118.             temp.append(this.m_buf.charAt(buflen_minus1));
  119.             this.m_buf.setLength(buflen_minus1);
  120.             if (this.m_buf.length() > 0) {
  121.                this.m_callback.handleContent(this.m_buf);
  122.             }
  123.  
  124.             if (temp.length() > 0) {
  125.                this.m_callback.handleContent(temp);
  126.             }
  127.  
  128.             this.m_buf.setLength(0);
  129.             return;
  130.          }
  131.  
  132.          if (i < buflen - 1 && buflen > 1) {
  133.             StringBuffer temp = new StringBuffer();
  134.  
  135.             for(int j = i + 1; j < buflen; ++j) {
  136.                temp.append(this.m_buf.charAt(j));
  137.             }
  138.  
  139.             this.m_buf.setLength(i + 1);
  140.             this.m_callback.handleContent(this.m_buf);
  141.             this.m_buf.setLength(0);
  142.             if (temp.length() > 0) {
  143.                this.m_callback.handleContent(temp);
  144.             }
  145.  
  146.             return;
  147.          }
  148.  
  149.          this.m_callback.handleContent(this.m_buf);
  150.          this.m_buf.setLength(0);
  151.       } else {
  152.          int buflen = this.m_buf.length();
  153.  
  154.          int i;
  155.          for(i = buflen - 1; i >= 0 && !Character.isWhitespace(this.m_buf.charAt(i)); --i) {
  156.          }
  157.  
  158.          if (i < 0) {
  159.             this.m_callback.handleContent(this.m_buf);
  160.          } else {
  161.             StringBuffer temp = new StringBuffer();
  162.             if (i == buflen - 1) {
  163.                temp.append(this.m_buf.charAt(i));
  164.                if (buflen > 1) {
  165.                   this.m_buf.setLength(buflen - 1);
  166.                   this.m_callback.handleContent(this.m_buf);
  167.                }
  168.  
  169.                this.m_callback.handleContent(temp);
  170.             } else {
  171.                for(int j = i + 1; j <= buflen - 1; ++j) {
  172.                   temp.append(this.m_buf.charAt(j));
  173.                }
  174.  
  175.                this.m_buf.setLength(i + 1);
  176.                this.m_callback.handleContent(this.m_buf);
  177.                if (temp.length() > 0) {
  178.                   this.m_callback.handleContent(temp);
  179.                }
  180.             }
  181.          }
  182.  
  183.          this.m_buf.setLength(0);
  184.       }
  185.  
  186.    }
  187.  
  188.    private int checkRenderable(int c) {
  189.       switch (c) {
  190.          case 146:
  191.          case 8217:
  192.             return 39;
  193.          case 149:
  194.             return 42;
  195.          case 8212:
  196.             return 45;
  197.          case 8226:
  198.             return 183;
  199.          default:
  200.             return c;
  201.       }
  202.    }
  203.  
  204.    public void finishedParsing() {
  205.    }
  206.  
  207.    public File getSourceFile(URL u, String path) {
  208.       File f = new File(path);
  209.  
  210.       try {
  211.          FileOutputStream fs = new FileOutputStream(f);
  212.          this.m_out = new BufferedOutputStream(fs);
  213.          this.parse(u.openConnection());
  214.          this.m_out.close();
  215.       } catch (IOException e) {
  216.          System.out.println("IOException getSourceFile: " + e);
  217.          f = null;
  218.       } finally {
  219.          this.m_out = null;
  220.       }
  221.  
  222.       return f;
  223.    }
  224.  
  225.    public void handleContent(StringBuffer txt) {
  226.    }
  227.  
  228.    public void handleNoBreakSpace() {
  229.    }
  230.  
  231.    public void handleTag(Tag t, boolean bStartTag) {
  232.    }
  233.  
  234.    private void insertLineBreak() {
  235.       this.m_callback.handleTag(this.m_generator.getTag(HTMLDefs.getName(7)), true);
  236.    }
  237.  
  238.    private boolean isNewlineCharacter(int c) {
  239.       switch (c) {
  240.          case 10:
  241.          case 13:
  242.             return true;
  243.          default:
  244.             return false;
  245.       }
  246.    }
  247.  
  248.    private boolean isSpace(int c) {
  249.       return c >= 0 && c < 256 ? (m_ctype[c] & 1) != 0 : false;
  250.    }
  251.  
  252.    private boolean notifyTagEncountered() {
  253.       Tag tag = null;
  254.       String buf = this.m_buf.toString();
  255.       int len = buf.length();
  256.       int idx = 0;
  257.  
  258.       for(int begin = 0; idx < len && this.isSpace(buf.charAt(idx)); ++idx) {
  259.       }
  260.  
  261.       if (idx == len) {
  262.          return false;
  263.       } else {
  264.          int var9;
  265.          for(var9 = idx; idx < len && !this.isSpace(buf.charAt(idx)); ++idx) {
  266.          }
  267.  
  268.          String token = buf.substring(var9, idx);
  269.          boolean bStartTag = token.charAt(0) != '/';
  270.          if (!bStartTag) {
  271.             tag = this.m_generator.getTag(token.substring(1));
  272.          } else {
  273.             tag = this.m_generator.getTag(token);
  274.          }
  275.  
  276.          if (tag == null) {
  277.             return false;
  278.          } else {
  279.             while(idx < len && this.isSpace(buf.charAt(idx))) {
  280.                ++idx;
  281.             }
  282.  
  283.             if (idx != len) {
  284.                this.parseAttributes(tag, buf, idx);
  285.             }
  286.  
  287.             if (tag.getID() == 28) {
  288.                this.insertLineBreak();
  289.             }
  290.  
  291.             if (bStartTag) {
  292.                this.m_callback.handleTag(tag, true);
  293.             } else {
  294.                this.m_callback.handleTag(tag, false);
  295.             }
  296.  
  297.             if (this.m_bSpace && this.m_lastTag != null && this.m_lastTag.breaksFlow()) {
  298.                this.m_bSpace = false;
  299.             }
  300.  
  301.             this.m_lastTag = tag;
  302.             if (this.m_bPreformat && !bStartTag && tag.getID() == 28) {
  303.                this.m_bPreformat = false;
  304.             } else if (bStartTag && tag.getID() == 28) {
  305.                this.m_bPreformat = true;
  306.             }
  307.  
  308.             if (this.m_lastTag.getID() == 49 && bStartTag) {
  309.                this.m_parserState = 7;
  310.             } else {
  311.                this.m_parserState = 1;
  312.             }
  313.  
  314.             return true;
  315.          }
  316.       }
  317.    }
  318.  
  319.    public void parse(Reader r, URL baseURL) throws IOException {
  320.       this.m_in = r;
  321.       this.m_buf.setLength(0);
  322.       this.m_callback.startingParsing((URL)null);
  323.       this.parseContent();
  324.       this.m_callback.finishedParsing();
  325.    }
  326.  
  327.    public void parse(URL u) throws IOException {
  328.       this.beginParsing(u.openConnection());
  329.    }
  330.  
  331.    public void parse(URLConnection con) throws IOException {
  332.       this.beginParsing(con);
  333.    }
  334.  
  335.    private void parseAttributes(Tag tag, String buf, int idx) {
  336.       int len = buf.length();
  337.       int begin = 0;
  338.  
  339.       while(true) {
  340.          String name;
  341.          int end;
  342.          while(true) {
  343.             while(true) {
  344.                label114:
  345.                while(true) {
  346.                   if (idx >= len) {
  347.                      return;
  348.                   }
  349.  
  350.                   while(idx < len && this.isSpace(buf.charAt(idx))) {
  351.                      ++idx;
  352.                   }
  353.  
  354.                   if (idx != len) {
  355.                      begin = idx;
  356.                      if (buf.charAt(idx) == '"') {
  357.                         ++idx;
  358.  
  359.                         while(idx < len && buf.charAt(idx) != '"') {
  360.                            ++idx;
  361.                         }
  362.  
  363.                         if (idx != len) {
  364.                            ++idx;
  365.                            break;
  366.                         }
  367.                      } else {
  368.                         if (buf.charAt(idx) != '\'') {
  369.                            while(true) {
  370.                               if (idx >= len || this.isSpace(buf.charAt(idx)) || buf.charAt(idx) == '=') {
  371.                                  break label114;
  372.                               }
  373.  
  374.                               ++idx;
  375.                            }
  376.                         }
  377.  
  378.                         ++idx;
  379.  
  380.                         while(idx < len && buf.charAt(idx) != '\'') {
  381.                            ++idx;
  382.                         }
  383.  
  384.                         if (idx != len) {
  385.                            ++idx;
  386.                            break;
  387.                         }
  388.                      }
  389.                   }
  390.                }
  391.  
  392.                name = buf.substring(begin, idx).toLowerCase();
  393.                if (idx < len && this.isSpace(buf.charAt(idx))) {
  394.                   while(idx < len && this.isSpace(buf.charAt(idx))) {
  395.                      ++idx;
  396.                   }
  397.                }
  398.  
  399.                if (idx != len && buf.charAt(idx) == '=') {
  400.                   ++idx;
  401.                   if (idx != len) {
  402.                      if (buf.charAt(idx) != ' ') {
  403.                         break;
  404.                      }
  405.  
  406.                      while(idx < len && this.isSpace(buf.charAt(idx))) {
  407.                         ++idx;
  408.                      }
  409.  
  410.                      if (idx != len) {
  411.                         break;
  412.                      }
  413.                   }
  414.                } else if (tag != null) {
  415.                   tag.setAttribute(name, "");
  416.                }
  417.             }
  418.  
  419.             begin = idx;
  420.             if (buf.charAt(idx) == '"') {
  421.                ++idx;
  422.  
  423.                for(begin = idx; idx < len && buf.charAt(idx) != '"'; ++idx) {
  424.                }
  425.  
  426.                if (idx != len) {
  427.                   end = idx++;
  428.                   break;
  429.                }
  430.             } else {
  431.                if (buf.charAt(idx) == '\'') {
  432.                   ++idx;
  433.  
  434.                   for(begin = idx; idx < len && buf.charAt(idx) != '\''; ++idx) {
  435.                   }
  436.  
  437.                   if (idx == len) {
  438.                      continue;
  439.                   }
  440.  
  441.                   end = idx++;
  442.                   break;
  443.                }
  444.  
  445.                while(idx < len && !this.isSpace(buf.charAt(idx))) {
  446.                   ++idx;
  447.                }
  448.  
  449.                end = idx;
  450.                break;
  451.             }
  452.          }
  453.  
  454.          String value = buf.substring(begin, end);
  455.          if (tag != null) {
  456.             tag.setAttribute(name, value);
  457.          }
  458.       }
  459.    }
  460.  
  461.    private void parseComment() {
  462.       if (this.m_ch == 62 && this.m_comment >= 2) {
  463.          this.m_buf.setLength(0);
  464.          this.m_comment = 0;
  465.          this.m_parserState = 1;
  466.       } else {
  467.          if (this.m_ch == 45) {
  468.             ++this.m_comment;
  469.          } else {
  470.             this.m_comment = 0;
  471.          }
  472.  
  473.       }
  474.    }
  475.  
  476.    private void parseContent() throws IOException {
  477.       boolean bPreformated = false;
  478.       this.m_bSpace = false;
  479.  
  480.       while(true) {
  481.          this.readChar();
  482.          if (this.m_ch < 0) {
  483.             int state = this.m_parserState;
  484.             if (this.m_buf.length() > 0 && state == 1) {
  485.                this.m_callback.handleContent(this.m_buf);
  486.             }
  487.  
  488.             return;
  489.          }
  490.  
  491.          this.m_ch = this.checkRenderable(this.m_ch);
  492.          switch (this.m_parserState) {
  493.             case 1:
  494.                this.parseText();
  495.                continue;
  496.             case 2:
  497.                this.parseTag();
  498.                continue;
  499.             case 3:
  500.                this.parseComment();
  501.             case 4:
  502.             default:
  503.                continue;
  504.             case 5:
  505.                if (this.m_ch == 62) {
  506.                   this.m_parserState = 2;
  507.                } else {
  508.                   this.m_buf.append((char)this.m_ch);
  509.                   if (this.m_ch == this.m_tagquote) {
  510.                      this.m_parserState = 2;
  511.                   }
  512.                }
  513.                continue;
  514.             case 6:
  515.                this.parseEntityReference();
  516.                continue;
  517.             case 7:
  518.          }
  519.  
  520.          int i;
  521.          switch (this.m_ch) {
  522.             case 60:
  523.                if (this.m_script == 0) {
  524.                   ++this.m_script;
  525.                   this.m_scriptBuffer.append((char)this.m_ch);
  526.                   continue;
  527.                }
  528.  
  529.                this.m_script = 0;
  530.                if (this.m_scriptBuffer.length() > 0) {
  531.                   for(int i = 0; i < this.m_scriptBuffer.length(); ++i) {
  532.                      this.m_buf.append(this.m_scriptBuffer.charAt(i));
  533.                   }
  534.  
  535.                   this.m_scriptBuffer.setLength(0);
  536.                   this.m_buf.append((char)this.m_ch);
  537.                }
  538.                continue;
  539.             default:
  540.                if (this.m_script <= 0) {
  541.                   this.m_buf.append((char)this.m_ch);
  542.                   continue;
  543.                }
  544.  
  545.                if (m_scriptTag[this.m_script] == Character.toLowerCase((char)this.m_ch)) {
  546.                   if (this.m_script == m_scriptTag.length - 1) {
  547.                      this.m_script = 0;
  548.                      this.m_scriptBuffer.setLength(0);
  549.                      if (this.m_buf.length() > 0) {
  550.                         this.callbackContent();
  551.                      }
  552.  
  553.                      this.m_callback.handleTag(this.m_generator.getTag(HTMLDefs.getName(49)), false);
  554.                      this.m_parserState = 1;
  555.                   } else {
  556.                      this.m_scriptBuffer.append((char)this.m_ch);
  557.                      ++this.m_script;
  558.                   }
  559.                   continue;
  560.                }
  561.  
  562.                this.m_script = 0;
  563.                i = 0;
  564.          }
  565.  
  566.          while(i < this.m_scriptBuffer.length()) {
  567.             this.m_buf.append(this.m_scriptBuffer.charAt(i));
  568.             ++i;
  569.          }
  570.  
  571.          this.m_scriptBuffer.setLength(0);
  572.          this.m_buf.append((char)this.m_ch);
  573.       }
  574.    }
  575.  
  576.    private void parseEntityReference() throws IOException {
  577.       if (this.m_ch == 35) {
  578.          int n = 0;
  579.          this.readChar();
  580.          if (this.m_ch >= 48 && this.m_ch <= 57) {
  581.             while(this.m_ch >= 48 && this.m_ch <= 57) {
  582.                n = n * 10 + this.m_ch - 48;
  583.                this.readChar();
  584.             }
  585.  
  586.             if (n == 9) {
  587.                for(int i = 0; i < 3; ++i) {
  588.                   this.m_buf.append(' ');
  589.                }
  590.             } else {
  591.                n = this.checkRenderable(n);
  592.                this.m_buf.append((char)n);
  593.             }
  594.  
  595.             if (this.m_ch == 59) {
  596.                this.m_parserState = 1;
  597.             } else {
  598.                this.resynchronize();
  599.             }
  600.          } else {
  601.             if (this.m_buf.length() == 0 && this.m_lastTag != null && this.m_lastTag.breaksFlow()) {
  602.                this.m_bSpace = false;
  603.             }
  604.  
  605.             if (this.m_bSpace) {
  606.                this.m_buf.append(' ');
  607.                this.m_bSpace = false;
  608.             }
  609.  
  610.             this.m_buf.append('&');
  611.             this.m_buf.append('#');
  612.             this.m_parserState = 1;
  613.          }
  614.       } else {
  615.          if (this.m_buf.length() == 0 && this.m_lastTag != null && this.m_lastTag.breaksFlow()) {
  616.             this.m_bSpace = false;
  617.          }
  618.  
  619.          if (this.m_bSpace) {
  620.             this.m_buf.append(' ');
  621.             this.m_bSpace = false;
  622.          }
  623.  
  624.          if (this.parseIdentifier(false)) {
  625.             Character c = (Character)m_escapes.get(this.m_entityBuffer.toString());
  626.             if (c != null) {
  627.                if (c == ' ') {
  628.                   int buflen = this.m_buf.length();
  629.                   if (buflen > 0) {
  630.                      int pos;
  631.                      for(pos = buflen - 1; pos >= 0 && !Character.isWhitespace(this.m_buf.charAt(pos)); --pos) {
  632.                      }
  633.  
  634.                      if (pos < 0) {
  635.                         this.m_callback.handleContent(this.m_buf);
  636.                      } else {
  637.                         StringBuffer temp = new StringBuffer();
  638.                         if (pos == buflen - 1) {
  639.                            --pos;
  640.                            pos = Math.max(0, pos);
  641.                         }
  642.  
  643.                         for(int j = pos + 1; j < buflen; ++j) {
  644.                            temp.append(this.m_buf.charAt(j));
  645.                         }
  646.  
  647.                         this.m_buf.setLength(pos + 1);
  648.                         this.m_callback.handleContent(this.m_buf);
  649.                         if (temp.length() > 0) {
  650.                            this.m_callback.handleContent(temp);
  651.                         }
  652.                      }
  653.                   }
  654.  
  655.                   this.m_buf.setLength(0);
  656.                   this.m_callback.handleNoBreakSpace();
  657.                   this.m_bNoBreakSpace = true;
  658.                } else {
  659.                   this.m_buf.append(c);
  660.                }
  661.  
  662.                if (this.m_ch == 59) {
  663.                   this.m_parserState = 1;
  664.                } else {
  665.                   this.resynchronize();
  666.                }
  667.  
  668.                return;
  669.             }
  670.          }
  671.  
  672.          this.m_buf.append('&');
  673.          if (this.m_entityBuffer.length() > 0) {
  674.             char[] dst = new char[this.m_entityBuffer.length()];
  675.             this.m_entityBuffer.getChars(0, this.m_entityBuffer.length(), dst, 0);
  676.             this.m_buf.append(dst);
  677.          }
  678.  
  679.          this.resynchronize();
  680.       }
  681.  
  682.    }
  683.  
  684.    private boolean parseIdentifier(boolean lower) throws IOException {
  685.       this.m_entityBuffer.setLength(0);
  686.       switch (this.m_ch) {
  687.          case 65:
  688.          case 66:
  689.          case 67:
  690.          case 68:
  691.          case 69:
  692.          case 70:
  693.          case 71:
  694.          case 72:
  695.          case 73:
  696.          case 74:
  697.          case 75:
  698.          case 76:
  699.          case 77:
  700.          case 78:
  701.          case 79:
  702.          case 80:
  703.          case 81:
  704.          case 82:
  705.          case 83:
  706.          case 84:
  707.          case 85:
  708.          case 86:
  709.          case 87:
  710.          case 88:
  711.          case 89:
  712.          case 90:
  713.             if (lower) {
  714.                this.m_ch = 97 + (this.m_ch - 65);
  715.             }
  716.             break;
  717.          case 91:
  718.          case 92:
  719.          case 93:
  720.          case 94:
  721.          case 95:
  722.          case 96:
  723.          default:
  724.             return false;
  725.          case 97:
  726.          case 98:
  727.          case 99:
  728.          case 100:
  729.          case 101:
  730.          case 102:
  731.          case 103:
  732.          case 104:
  733.          case 105:
  734.          case 106:
  735.          case 107:
  736.          case 108:
  737.          case 109:
  738.          case 110:
  739.          case 111:
  740.          case 112:
  741.          case 113:
  742.          case 114:
  743.          case 115:
  744.          case 116:
  745.          case 117:
  746.          case 118:
  747.          case 119:
  748.          case 120:
  749.          case 121:
  750.          case 122:
  751.       }
  752.  
  753.       while(true) {
  754.          this.m_entityBuffer.append((char)this.m_ch);
  755.          this.readChar();
  756.          switch (this.m_ch) {
  757.             case 45:
  758.             case 46:
  759.             case 48:
  760.             case 49:
  761.             case 50:
  762.             case 51:
  763.             case 52:
  764.             case 53:
  765.             case 54:
  766.             case 55:
  767.             case 56:
  768.             case 57:
  769.             case 95:
  770.             case 97:
  771.             case 98:
  772.             case 99:
  773.             case 100:
  774.             case 101:
  775.             case 102:
  776.             case 103:
  777.             case 104:
  778.             case 105:
  779.             case 106:
  780.             case 107:
  781.             case 108:
  782.             case 109:
  783.             case 110:
  784.             case 111:
  785.             case 112:
  786.             case 113:
  787.             case 114:
  788.             case 115:
  789.             case 116:
  790.             case 117:
  791.             case 118:
  792.             case 119:
  793.             case 120:
  794.             case 121:
  795.             case 122:
  796.                break;
  797.             case 47:
  798.             case 58:
  799.             case 59:
  800.             case 60:
  801.             case 61:
  802.             case 62:
  803.             case 63:
  804.             case 64:
  805.             case 91:
  806.             case 92:
  807.             case 93:
  808.             case 94:
  809.             case 96:
  810.             default:
  811.                return true;
  812.             case 65:
  813.             case 66:
  814.             case 67:
  815.             case 68:
  816.             case 69:
  817.             case 70:
  818.             case 71:
  819.             case 72:
  820.             case 73:
  821.             case 74:
  822.             case 75:
  823.             case 76:
  824.             case 77:
  825.             case 78:
  826.             case 79:
  827.             case 80:
  828.             case 81:
  829.             case 82:
  830.             case 83:
  831.             case 84:
  832.             case 85:
  833.             case 86:
  834.             case 87:
  835.             case 88:
  836.             case 89:
  837.             case 90:
  838.                if (lower) {
  839.                   this.m_ch = 97 + (this.m_ch - 65);
  840.                }
  841.          }
  842.       }
  843.    }
  844.  
  845.    private void parseTag() {
  846.       switch (this.m_ch) {
  847.          case 34:
  848.          case 39:
  849.             this.m_tagquote = this.m_ch;
  850.             this.m_buf.append((char)this.m_ch);
  851.             this.m_parserState = 5;
  852.             break;
  853.          case 60:
  854.             if (this.m_buf.length() > 0) {
  855.                if (this.notifyTagEncountered()) {
  856.                   this.m_parserState = 2;
  857.                   this.m_buf.setLength(0);
  858.                } else {
  859.                   this.m_buf.setLength(0);
  860.                }
  861.             }
  862.             break;
  863.          case 62:
  864.             if (this.m_buf.length() > 0) {
  865.                if (this.notifyTagEncountered()) {
  866.                   this.m_parserState = 1;
  867.                } else {
  868.                   this.m_parserState = 1;
  869.                }
  870.  
  871.                this.m_buf.setLength(0);
  872.             }
  873.             break;
  874.          default:
  875.             if (this.m_ch == 45 && this.m_buf.length() == 2 && this.m_buf.charAt(1) == '-' && this.m_buf.charAt(0) == '!') {
  876.                this.m_buf.setLength(0);
  877.                this.m_parserState = 3;
  878.             } else {
  879.                this.m_buf.append((char)this.m_ch);
  880.             }
  881.       }
  882.  
  883.    }
  884.  
  885.    private void parseText() {
  886.       if (!this.m_bPlainText && !this.m_bPreformat) {
  887.          switch (this.m_ch) {
  888.             case 38:
  889.                this.m_parserState = 6;
  890.                break;
  891.             case 60:
  892.                this.m_parserState = 2;
  893.                if (this.m_buf.length() > 0) {
  894.                   this.callbackContent();
  895.                }
  896.                break;
  897.             default:
  898.                if (this.isSpace(this.m_ch)) {
  899.                   this.m_bSpace = true;
  900.                } else {
  901.                   if (this.m_buf.length() == 0 && this.m_lastTag != null && this.m_lastTag.breaksFlow()) {
  902.                      this.m_bSpace = false;
  903.                   }
  904.  
  905.                   if (this.m_bSpace) {
  906.                      this.m_buf.append(' ');
  907.                      this.m_bSpace = false;
  908.                   }
  909.  
  910.                   this.m_buf.append((char)this.m_ch);
  911.                }
  912.          }
  913.  
  914.       } else {
  915.          switch (this.m_ch) {
  916.             case 9:
  917.                for(int i = 0; i < 3; ++i) {
  918.                   this.m_buf.append(' ');
  919.                }
  920.                break;
  921.             case 10:
  922.                if (this.m_buf.length() > 0) {
  923.                   this.callbackContent();
  924.                }
  925.  
  926.                this.insertLineBreak();
  927.             case 13:
  928.                break;
  929.             case 38:
  930.                this.m_parserState = 6;
  931.                break;
  932.             case 60:
  933.                if (!this.m_bPlainText) {
  934.                   this.m_parserState = 2;
  935.                   if (this.m_buf.length() > 0) {
  936.                      this.callbackContent();
  937.                   }
  938.                }
  939.                break;
  940.             default:
  941.                this.m_buf.append((char)this.m_ch);
  942.          }
  943.  
  944.       }
  945.    }
  946.  
  947.    private void readChar() throws IOException {
  948.       this.m_ch = this.m_in.read();
  949.       if (this.m_out != null && this.m_ch >= 0) {
  950.          this.m_out.write(this.m_ch);
  951.       }
  952.  
  953.    }
  954.  
  955.    private void resynchronize() {
  956.       switch (this.m_ch) {
  957.          case 38:
  958.             this.m_parserState = 6;
  959.             break;
  960.          case 60:
  961.             this.m_parserState = 2;
  962.             if (this.m_buf.length() > 0) {
  963.                if (this.m_bSpace) {
  964.                   this.m_buf.append(' ');
  965.                }
  966.  
  967.                this.callbackContent();
  968.             }
  969.             break;
  970.          default:
  971.             if (this.m_bSpace) {
  972.                this.m_buf.append(' ');
  973.             }
  974.  
  975.             this.m_buf.append((char)this.m_ch);
  976.             this.m_parserState = 1;
  977.       }
  978.  
  979.    }
  980.  
  981.    public void setCallback(ParserCallback cb) {
  982.       this.m_bPlainText = false;
  983.       this.m_callback = cb;
  984.       this.m_lineNum = 0;
  985.       this.m_buf.setLength(0);
  986.       this.m_entityBuffer.setLength(0);
  987.       this.m_parserState = 1;
  988.       this.m_bPreformat = false;
  989.       this.m_lastTag = null;
  990.       this.m_bSpace = false;
  991.    }
  992.  
  993.    public void setTagGenerator(TagGenerator generator) {
  994.       if (generator != null) {
  995.          this.m_generator = generator;
  996.       }
  997.  
  998.    }
  999.  
  1000.    public void startingParsing(URL u) {
  1001.    }
  1002. }
  1003.